import Utils from "../../Utils";
import UiPointer from "../UI/UiPointer";
import Dialog from "../dialog/Dialog";
import DomainDialog from "../dialog/DomainDialog";
import DestructibleFacility from "../facility/DestructibleFacility";
import Mine from "../facility/pulbicFacility/Mine";
import { Killer } from "../funcObj/interface/HealthPoint";
import { FacilityType } from "../info/GameEnum";
import { Global } from "../info/Global";
import { Location, PlayerColors } from "../info/Predefine";
import Player from "../player/Player";
import GameManager from "./GameManager";
import NodePoolManager from "./NodePoolManager";
import PlayerManager from "./PlayerManager";

const { ccclass, property } = cc._decorator;

/**
 * 设施名对应的弹窗名
 */
const facilityDialogName = new Map();
facilityDialogName.set("主基地", "主基地");
facilityDialogName.set("晶矿", "晶矿");
facilityDialogName.set("油矿", "油矿");
facilityDialogName.set("采油机", "油矿");
facilityDialogName.set("黑洞发生器", "黑洞发生器");

@ccclass
export default class UiManager extends cc.Component {

    public static instance: UiManager = null;

    @property(cc.Camera)
    gameCamera: cc.Camera = null;

    @property(cc.Label)
    diamondLabel: cc.Label = null;

    @property(cc.Label)
    oilLabel: cc.Label = null;

    @property(cc.Label)
    timeLabel: cc.Label = null;

    @property(cc.Node)
    headsParent: cc.Node = null;

    @property(cc.Node)
    pointer: cc.Node = null;

    @property(cc.Node)
    dialogParent: cc.Node = null;

    @property(cc.Node)
    tipNode: cc.Node = null;

    @property([cc.Prefab])
    dialogPrefabs: cc.Prefab[] = [];

    @property([cc.SpriteFrame])
    headFrames: cc.SpriteFrame[] = [];

    @property([cc.SpriteFrame])
    imgSelfFrame: cc.SpriteFrame[] = [];

    @property([cc.SpriteFrame])
    imgFrame: cc.SpriteFrame[] = [];

    gameTime = 0;
    onLoad() {
        UiManager.instance = this;

        //动态加载玩家头像
        let players = PlayerManager.instance.playerParent.getComponentsInChildren(Player);
        players.forEach((player, index) => {
            let playerId = player.playerId,
                roleId = player.roleId,
                imgF: cc.SpriteFrame,
                HeadF = this.headFrames[roleId],
                headChildSprites = this.headsParent.children[index].getComponentsInChildren(cc.Sprite),
                mask = this.headsParent.children[index].getChildByName("mask");

            //用于判断发现的是谁
            this.headsParent.children[index]['playerId'] = playerId;
            if (player == PlayerManager.instance.controllerPlayer) {
                imgF = this.imgSelfFrame[player.playerId];
                this.headsParent.children[index].getChildByName("self").active = true;
                mask.destroy();
            } else {
                imgF = this.imgFrame[player.playerId];
                this.headsParent.children[index].getChildByName("self").destroy();
                mask.active = true;
                mask.children[1].getComponent(cc.Label).string = playerId.toString();
            }
            headChildSprites[0].spriteFrame = imgF;
            headChildSprites[1].spriteFrame = HeadF;
        })

        this.dialogParent.children.forEach(item => item.active = false);
    }

    protected start(): void {
        //监听玩家资源变化
        PlayerManager.instance.controllerPlayer.node.on(Player.EventType.更新晶石, this.refreshDiamond, this);
        PlayerManager.instance.controllerPlayer.node.on(Player.EventType.更新石油, this.refreshOil, this);
        //监听发现新对手
        PlayerManager.instance.controllerPlayer.node.on(Player.EventType.找到新的对手, this.onFindNewEnemy, this);
        //监听玩家新飞行物
        PlayerManager.instance.controllerPlayer.node.on(Player.EventType.更新飞行物数量, this.onAddFlyerCount, this);
        //监听玩家基地被摧毁
        PlayerManager.instance.playerParent.children.forEach(node => node.on(Player.EventType.基地被摧毁, this.onPlayerDie, this));

        if (Global.gameInfo.gameTime < 3) {
            this.scheduleOnce(() => {
                this.openDialogByName("帮助");
            }, 0.2);
        }

        Global.gameInfo.gameTime++;
        Global.saveGameInfo();
    }

    /**
     * 钻石矿
     */
    refreshDiamond(diamond: number) {
        this.diamondLabel.string = diamond.toString();
    }

    /**
     * 石油矿
     */
    refreshOil(oil: number) {
        this.oilLabel.string = oil.toString();
    }

    /**
     * 电脑基地被摧毁
     * @param killer 
     */
    onPlayerDie(killer: Killer, player: Player) {
        UiManager.instance.showTip(`${player.playerName}被${killer.player.playerName}消灭`);
        let headNode = this.headsParent.children.find(node => node['playerId'] == player.playerId);
        headNode.getChildByName("xDie").active = true;

        if (player == PlayerManager.instance.controllerPlayer || PlayerManager.instance.isWiner()) {
            this.openGameOverDialog();
        }
    }

    /**
     * 当玩家新发现了敌人
     * @param locations 
     */
    onFindNewEnemy(player: Player) {
        //修改头像状态
        let headNode = this.headsParent.children.find(node => node['playerId'] == player.playerId);
        headNode.getChildByName("mask").active = false;
        this.showTip("发现敌人 " + player.playerName)
    }

    /**
     * 当玩家刷新了新的飞行物
     * @param facilityType 
     * @param sum 
     */
    onAddFlyerCount(facilityType: FacilityType, sum: number) {
        if (sum == 1) {
            let name = Global.getFacilityInfo<{ 飞行物名字: string }>(facilityType).飞行物名字;
            this.showTip(name + "已就绪");
        }
    }

    showTip(tip: string) {
        let tipNode = NodePoolManager.instance.obtain(NodePoolManager.instance.inforTipPrefab);

        tipNode.children[0].active = tipNode.children[1].active = false;
        if (tip.indexOf("击杀奖励") >= 0) {
            tipNode.children[0].active = true;
            if (/\+.*\+/.test(tip)) {
                tipNode.children[1].active = true;
                tipNode.children[0].x = -16;
                tipNode.children[1].x = 86;
            } else {
                tipNode.children[1].active = false;
                tipNode.children[0].x = 33;
            }
        }

        tipNode.getComponentInChildren(cc.Label).string = tip;
        tipNode.active = true;
        tipNode.parent = this.tipNode;
        tipNode.stopAllActions();
        tipNode.y = 150;
        tipNode.opacity = 255;
        cc.tween(tipNode)
            .parallel(
                cc.tween()
                    .to(2, { y: 230 }),
                cc.tween()
                    .delay(1)
                    .to(1, { opacity: 0 })
            )
            .call(() => {
                NodePoolManager.instance.recycle(tipNode);
            })
            .start();
    }

    /**
     * 打开设施功能弹窗
     * @param location 
     */
    async openLocationDialog(location: Location) {
        let isSelfDomain = PlayerManager.instance.controllerPlayer.isSelfDomain(location);
        let facility = GameManager.instance.getFacilityByLocation(location);
        let isHide = !PlayerManager.instance.controllerPlayer.isLocationVisible(location);

        if (isHide) {
            this.openDialogByName("派遣", location, isHide);
        } else {
            if (isSelfDomain) {
                if (facility && facility.facilityType != FacilityType.安家点) {
                    if (facility instanceof DestructibleFacility) {
                        if (facility.player == PlayerManager.instance.controllerPlayer) {
                            let dialogName = facilityDialogName.get(facility.node.name);
                            if (!dialogName) dialogName = "升级和卖出";
                            this.openDialogByName(dialogName, facility);
                        } else {
                            this.openDialogByName("派遣", location, isHide);
                        }
                    } else {
                        let dialogName = facilityDialogName.get(facility.node.name);
                        this.openDialogByName(dialogName, facility);
                    }
                } else {
                    if (DomainDialog.Locked) return;
                    this.openDialogByName("建造", location);
                }
            } else {
                //避免失去领地后，领地内的设施
                if (facility instanceof DestructibleFacility && facility.player == PlayerManager.instance.controllerPlayer) {
                    let dialogName = facilityDialogName.get(facility.node.name);
                    if (!dialogName) dialogName = "升级和卖出";
                    this.openDialogByName(dialogName, facility);
                } else if (facility instanceof Mine) {
                    if (facility.facilityType == FacilityType.晶矿) {
                        this.openDialogByName("晶矿", facility)
                    } else if (facility.facilityType == FacilityType.油矿) {
                        this.openDialogByName("油矿", facility)
                    } else {
                        return cc.error("不是晶矿也不是油矿！")
                    }
                } else {
                    this.openDialogByName("派遣", location, isHide);
                }
            }
        }
    }

    /**
     * 打开暂停弹窗
     * @param location 
     */
    openPauseDialog() {
        //如果主基地在画面内才打开，不在则返回主基地
        let mainhome = PlayerManager.instance.controllerPlayer.facilityArr[FacilityType.主基地][0];
        if (!mainhome) {
            this.openDialogByName("暂停");
            return;
        }
        if (Utils.checkInView(mainhome.node, this.gameCamera)) {
            this.openDialogByName("暂停");
        } else {
            UiPointer.instance.currLocation = mainhome.locations[0];
        }
    }

    /**
     * 打开游戏结束弹窗
     * @param winer 
     */
    openGameOverDialog() {
        this.scheduleOnce(() => {
            GameManager.instance.clearALL();
            this.openDialogByName("游戏结束");
        }, 2);
    }

    private openDialogByName(dialogName: string, ...args: any[]): cc.Node {
        let dialog = this.dialogParent.getChildByName(dialogName);
        if (!dialog) {
            let prefab = this.dialogPrefabs.find(item => item.name == dialogName);
            dialog = cc.instantiate(prefab);
        }
        let dialogComp = dialog.getComponent(Dialog);
        dialogComp && dialogComp.init(...args);
        dialog.parent = this.dialogParent;
        dialog.active = true;
        return dialog;
    }

    onClick(event: cc.Event) {
        let name = event.target.name;
        switch (name) {
            case "安家":
                PlayerManager.instance.controllerPlayer.makeHome();
                break;
            default:
                break;
        }
    }

    protected update(dt: number): void {
        this.gameTime += dt;
        let gameTime = Math.floor(this.gameTime);
        const minutes = Math.floor(gameTime / 60);
        const seconds = gameTime % 60;
        this.timeLabel.string = `${minutes}空s空${seconds}`;
    }
}
